#include "display.h"

#include "accelerometer.h"
#include "h01.h"
#include <stm32f10x_it.h>

/*
Y0  PA08: D01......D10, PB03: D59......D51
Y1  PA09: D11......D20, PB04: D68......D60
Y2  PA10: D21......D30, PB05: D77......D69
Y3  PB02: D31......D40, PB06: D86......D78
Y4  PB01: D41......D50, PB07: D95......D87

PC03 - PC12: X0......................X9
*/

#define	MODEN_FONT
#ifdef	MODEN_FONT
static ushort	maskA[]={
	0x0078,0x0088,0x00f0, 0x0080,0x00f8,0x0090,	// 0,1
	0x00b0,0x00c8,0x0090, 0x0058,0x00a8,0x0088,	// 2,3
	0x00f8,0x0050,0x0060, 0x0068,0x00a8,0x00b8,	// 4,5
	0x0060,0x00a8,0x00f0, 0x0018,0x00e8,0x0008,	// 6,7
	0x0078,0x00a8,0x00f0, 0x0078,0x00a8,0x0030,	// 8,9
	0x00f0,0x0048,0x00f0, 0x0050,0x00a8,0x00f8,	// a,b
	0x0088,0x0088,0x0070, 0x0070,0x0088,0x00f8,	// c,d
	0x0088,0x00a8,0x00f8, 0x0008,0x0028,0x00f8,	// e,f
};
static ushort	maskB[]={
	0x0704,0x0102,0x0606, 0x0002,0x0706,0x0202,	// 0,1
	0x0602,0x0106,0x0202, 0x0304,0x0502,0x0102,	// 2,3
	0x0706,0x0204,0x0404, 0x0504,0x0502,0x0702,	// 4,5
	0x0404,0x0502,0x0606, 0x0300,0x0506,0x0100,	// 6,7
	0x0704,0x0502,0x0606, 0x0704,0x0502,0x0600,	// 8,9
	0x0606,0x0104,0x0606, 0x0204,0x0502,0x0706,	// a,b
	0x0102,0x0102,0x0604, 0x0604,0x0102,0x0706,	// c,d
	0x0102,0x0502,0x0706, 0x0100,0x0500,0x0706,	// e,f
};
#else
static ushort	maskA[]={
	0x00f8,0x0088,0x00f8, 0x0000,0x00f8,0x0000,	// 0,1
	0x00b8,0x00a8,0x00e8, 0x00f8,0x00a8,0x00a8,	// 2,3
	0x00f8,0x0020,0x0038, 0x00e8,0x00a8,0x00b8,	// 4,5
	0x00e0,0x00a0,0x00f8, 0x00f8,0x0008,0x0008,	// 6,7
	0x00f8,0x00a8,0x00f8, 0x00f8,0x00a8,0x00b8,	// 8,9
};
static ushort	maskB[]={
	0x0706,0x0102,0x0706, 0x0000,0x0706,0x0000,	// 0,1
	0x0702,0x0502,0x0506, 0x0706,0x0502,0x0502,	// 2,3
	0x0706,0x0400,0x0700, 0x0506,0x0502,0x0702,	// 4,5
	0x0406,0x0402,0x0706, 0x0706,0x0100,0x0100,	// 6,7
	0x0706,0x0502,0x0706, 0x0706,0x0502,0x0702,	// 8,9
};
#endif // MODEN_FONT

static ushort	matrixA[10],matrixB[10];
static ushort	*pointer;
static ubyte	savBar	=0xff;
static ubyte	savBat	=0xff;
static uint		savDec	=0xffffffffL;
static uint		savHex	=0xffffffffL;
static uint		savTme	=0xffffffffL;

static void clearMatrix(void){
	uint *e=(uint*)matrixA+5,*p;
	for(p=(uint*)matrixA;p<e;)
		*p++=0;
	pointer=matrixA;
}
static void pinOff(void){
	GPIO_ResetBits(GPIOA,PIN_Y0_Y2);
	GPIO_ResetBits(GPIOB,PIN_Y3_Y9);
	GPIO_SetBits(GPIOC,PIN_X0_Y9);
}
static void pinOn(void){
}
static void resetSav(void){
	savBar=savBat=savDec=savHex=savTme=0xffffffffL;
}
static void timerOff(void){
	SysTick_Config(SystemCoreClock/10);	// Set SysTick base time to 200ms
}
static void timerOn(void){
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
	SysTick_Config(SystemCoreClock/2000);	// Set SysTick base time to 1ms
}

// -----------------------------------------------------------------------------

void SysTick_Handler(void){
	timer++;
	if(pointer){
		static ubyte x;
		GPIO_ResetBits(GPIOA,PIN_Y0_Y2);
		GPIO_ResetBits(GPIOB,PIN_Y3_Y9);
		GPIO_SetBits(GPIOC,PIN_X0_Y9);
		x=(x+1)%10;
		ushort v=pointer[x];
		GPIO_SetBits(GPIOA,v);
		GPIO_SetBits(GPIOB,v);
		GPIO_ResetBits(GPIOC,0x1000>>x);
		ADC_SoftwareStartConvCmd(ADC1,ENABLE);
	}
}

// -----------------------------------------------------------------------------

void displayOff(void){
	if(pointer){
		pointer=0;
		resetSav();
		timerOff();
		pinOff();
		fifoOn();
		RCC_HCLKConfig(RCC_SYSCLK_Div4);
	}
}
void displayOn(void){
	if(!pointer){
		RCC_HCLKConfig(RCC_SYSCLK_Div2);
		clearMatrix();
		pinOn();
		timerOn();
		fifoOff();
	}
}
void outBar(ubyte n){
	if(n==savBar)
		return;
	resetSav();
	savBar=n;
	ushort *e,*p,*t=pointer==matrixB?matrixA:matrixB;
	p=t;
	if(!n||n>37)for(e=t+10;p<e;)
		*p++=0;
	else if(n<11){
		for(e=t+n;p<e;)
			*p++=0x0706;
		for(e=t+10;p<e;)
			*p++=0;
	}else if(n<20){
		for(e=t+10;p<e;)
			*p++=0x0706;
		for(p=t+20-n,e=t+10;p<e;)
			*p++|=0x00f8;
	}else if(n<30){
		for(e=t+10;p<e;)
			*p++=0x00f8;
		for(p=t+n-19,e=t+10;p<e;)
			*p++|=0x0706;
	}else{
		for(e=t+39-n;p<e;)
			*p++=0x00f8;
		for(e=t+10;p<e;)
			*p++=0;
	}
	pointer=t;
}
void outBattery(ubyte n){
	if(n&&(timer&0x200))
		n--;
	if(n==savBat)
		return;
	resetSav();
	savBat=n;
	ushort *e,*p,*t=pointer==matrixB?matrixA:matrixB;
	for(p=t,e=t+6;p<e;)
		*p++=0;
	*p++=0x0606;
	for(e=t+7+(n<3?n:3);p<e;)
		*p++=0x0606;
	for(e=t+10;p<e;)
		*p++=0x0202;
	p=t+6;
	*p++|=0x0060;
	for(e=t+13-n;p<e;)
		*p++|=0x0090;
	for(e=t+10;p<e;)
		*p++|=0x00f0;
	pointer=t;
}
void outDec(uint number){
	if(number==savDec)
		return;
	resetSav();
	savDec=number;
	ushort *e,*p,*t=pointer==matrixB?matrixA:matrixB,*v;
	uint k=number,i;
	p=t;
	*p++=0;
	for(i=2;i;i--){
		for(e=p+3,v=maskA+k%10*3;p<e;)
			*p++=*v++;
		if(!(k/=10))
			break;
		*p++=0;
	}
	if(k){
		*p++=*(maskA+k%10*3);
		for(p=t+9,e=p-2,v=maskB+k%10*3+1;p>e;)
			*p--|=*v++;
		for(i=2;i;i--){
			if(!(k/=10))
				break;
			p--;
			for(e=p-3,v=maskB+k%10*3;p>e;)
				*p--|=*v++;
		}
	}else for(e=t+10;p<e;)
		*p++=0;
	pointer=t;
}
void outError(void){
	static ushort	matrix[10]={0,0x0400,0x0420,0x0420,0x0020,0x0400,0x0420,
		0x0420,0x0020,0x0204};
	resetSav();
	pointer=matrix;
}
void outHex(uint number){
	if(number==savHex)
		return;
	resetSav();
	savHex=number;
	ushort *e,*p,*t=pointer==matrixB?matrixA:matrixB,*v;
	uint k=number,i;
	p=t;
	*p++=0;
	for(i=2;i;i--){
		for(e=p+3,v=maskA+(k&15)*3;p<e;)
			*p++=*v++;
		k>>=4;
		*p++=0;
	}
	*p++=*(maskA+(k&15)*3);
	for(p=t+9,e=p-2,v=maskB+(k&15)*3+1;p>e;)
		*p--|=*v++;
	for(i=2;i;i--){
		k>>=4;
		p--;
		for(e=p-3,v=maskB+(k&15)*3;p>e;)
			*p--|=*v++;
	}
	pointer=t;
}
void outTime(uint time){
	if(time==savTme)
		return;
	resetSav();
	savTme=time;
	ushort *e,*p,*t=pointer==matrixB?matrixA:matrixB,*v;
	ushort k=time%60;
	p=t;
	*p++=0;
	*p++=0;
	for(ubyte i=2;i;i--){
		for(e=p+3,v=maskA+k%10*3;p<e;)
			*p++=*v++;
		k/=10;
		*p++=0;
	}
	p--;
	*p--|=0x204;
	if(!(k=time/60%12))
		k=12;
	for(ubyte i=2;i;i--){
		p--;
		for(e=p-3,v=maskB+k%10*3;p>e;)
			*p--|=*v++;
		if(!(k/=10))
			break;
	}
	pointer=t;
}